package com.owc.common.converter;

import com.owc.common.tool.ReflectionUtils;
import com.owc.common.tool.BeanUtils;
import org.springframework.lang.Nullable;

import java.lang.reflect.ParameterizedType;
import java.util.Objects;

/**
 * Converter interface for input
 * @author Xiaoming
 * @param <DOMAIN>
 */
public interface InputConverter<DOMAIN> extends Initialization<DOMAIN>{

    /**
     * Converter to DOMAIN
     * @return new domain with base example attr value
     */
    @SuppressWarnings("unchecked")
    default DOMAIN converterTo() throws Exception {
        //Get current params type.
        ParameterizedType currentType = parameterizedType();

        Objects.requireNonNull(currentType,"Get current converter type is null. But it must not null");
        //Get current class type.
        Class<DOMAIN> domainClass = (Class<DOMAIN>)currentType.getActualTypeArguments()[0];
        //Trans to DOMAIN
        DOMAIN domain = BeanUtils.transformFrom(this,domainClass);
        //If exist custom trans happening. please implement this function
        customConverter(domain);

        return domain;
    }

    /**
     * Get parameterized type.
     *
     * @return parameterized type or null
     */
    @Nullable
    default ParameterizedType parameterizedType() {
        return ReflectionUtils.getParameterizedType(InputConverter.class, this.getClass());
    }

    /**
     * Update a domain by dto.(shallow)
     *
     * @param domain updated domain
     */
    default void update(DOMAIN domain) {
        BeanUtils.updateProperties(this, domain);
    }

    /**
     * Custom trans implement
     * @return DOMAIN example
     */
    void customConverter(DOMAIN domain) throws Exception;
}
